package dcli;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Universidad Simón Bolívar
 * Curso de Redes I - Taller
 * Profesor: Ricardo Gonzalez
 * Trimestre Enero-Marzo 2011
 *
 * Proyecto 2 RD
 *
 * @author Grupo 9
 * @author Richard Simoes Ferreira
 * @author Ricardo Tocco
 *
 * @version 1.0
 *
 */
public class ErrorHandler {
    //Permite manejar los errores de dcli

    private ControlDcli control;

    /**
     * Constructor de la clase
     */
    public ErrorHandler (){
        control = null;
    }

    /**
     * Constructor de la clase
     */
    public ErrorHandler (ControlDcli c){
        this.control = c;
    }

    /**
     *  Obtiene la estructura de control dcli que está siendo utilizada por
     * el errorHandler
     * 
     * @return  la estructura de control que esta utilizando errorHandler
     */
    public ControlDcli getControlDcli(){
        return this.control;
    }

    /**
     * Establece la estructura de control dcli que usa errorHandler
     * 
     * @param c Estructura de control dcli
     */
    public void setControl(ControlDcli c){
        this.control = c;
    }

    /**
     * Imprime por salida estandar la ayuda de invocacion del programa principal,
     * si el mismo fue mal invocado y termina el programa.
     * 
     * @return void
     */

    public static void imprimirAyudaUsage () {
        System.err.println("\n+---- USAGE ----+\n\n");
        System.err.println("dcli [-h <host de un rep>] " +
                "[-p <puerto de un rep>] [-d <ldirectorio>] [-a <archivo>] " +
                "[-n <nombre>]\n\n");
        System.exit(-1);
    }

    /**
     * Error de argumentos en el programa principal
     */
    public void argumentosInvalidos (){
        System.err.println("ErrorHandler_Dcli: Se ha introducido un numero" +
                " inválido de" +
                " argumentos o algún argumento es desconocido");
        imprimirAyudaUsage();
    }

    /**
     * Redifinición una o más veces de un mismo argumento en el programa
     * principal
     * 
     * @param parametro Argumento redefinido una o más veces
     */
    public void redifinicionArgumento (String parametro){
        System.err.println("ErrorHandler_Dcli: Se ha redefinido "+parametro+
                " mas de una vez");
        imprimirAyudaUsage();
    }

    /**
     * Error de verificación de existencia del directorio <ldirectorio>
     * de entrada
     */
    public void directorioNoExiste(){
        System.err.println("ErrorHandler_Dcli: El directorio <ldirectorio>" +
                " (-d) introducido por el usuario no existe" +
                "o no ha podido ser localizado, por favor introduzca una " +
                "direccion absoluta válida");
        System.exit(-1);
    }

    /**
     * Error de verificación de existencia del directorio <ldirectorio> en ldir
     */
    public void directorioNoEncontrado(){
        System.err.println("ErrorHandler_Dcli: El directorio <ldirectorio>" +
                "no existeo no ha podido ser localizado.");
    }

    /**
     * Error de verificación de existencia del archivo -a de entrada
     */
    public void archivoNoExiste(){
        System.err.println("ErrorHandler_Dcli: El archivo introducido por " +
                "el usuario no existe" +
                " o no ha podido ser localizado, por favor introduzca una " +
                "direccion absoluta válida");
        System.exit(-1);
    }

    /**
     * Error de parametros desconocidos o inválidos
     */
    public void parametroInvalido(){
        System.err.println("ErrorHandler_Dcli: Uno o más parámetros inválidos " +
                "se han introducido");
        imprimirAyudaUsage();
    }

    /**
     * Error al momento establecer una conexion con el puerto bien conocido
     * de drep correspondiente
     * @param e         Excepcion del sistema
     * @param puerto    Puerto al cual no ha podido establecer conexion
     */
    public void errorPuertoConnect(IOException e, int puerto){
        System.err.println("ErrorHandler_Dcli: No se ha podido abrir el " +
                "socket en el puerto "+puerto+"");
        System.exit(-1);
    }

    /**
     * Error al momento de leer el archivo de comando introducido por el
     * usuario
     * @param e Excepcion del sistema
     */
    public void errorLecturaArchivoComandos(IOException e){
        System.err.println("ErrorHandler_Dcli: Se ha producido un error " +
                "en la lectura del archivo de comandos");
        System.exit(-1);
    }

    /**
     * Ayuda con los comandos aceptados por consola
     */
    public static void imprimirAyudaConsola(){
        System.out.println("Consola Dcli v1.0");
        System.out.println("Comandos :\n-------------");
        System.out.println("ldir \nrdir \ntuser\nnrep\n" +
                "sube <nombre_archivo>\nbaja <nombre_archivo>" +
                "\ncat <nombre_archivo>\nhelp\n--help\nq");
    }

    /**
     * El comando introducido por consola no se reconoce
     * @param comando   Comando que no ha podido ser reconocido
     */
    public void errorComandoDesconocido(String comando){
        System.err.println("ErrorHandler_Dcli: El comando introducido *"+
                comando+"* no es reconocido por favor intente de nuevo");
        imprimirAyudaConsola();

    }

    /**
     * El comando introducido desde el archivo de comandos no se reconoce
     * @param comando   Comando que no ha podido ser reconocido
     */
    public void errorComandoDesconocidoArch(String comando){
        System.err.println("ErrorHandler_Dcli: El comando introducido *"+
                comando+"* no es reconocido o le falta argumentos");

    }

    /**
     * Error de lectura en Consola
     * @param e Excepcion del sistema
     * @param control Estructura de control dcli
     */
    public void errorLecturaConsola(IOException e, ControlDcli control){
        System.err.println("ErrorHandler_Dcli: Se ha producido un error" +
                " de lectura en consola");
    }

    /**
     * Error al momento de desconectar el socket con el
     * drep correspondiente
     * @param e         Excepcion del sistema
     */
    public void errorSocketDisconnect(IOException e){
        System.err.println("ErrorHandler_Dcli: No se ha podido cerrar" +
                " correctamente el socket de comunicación con el respectivo" +
                "drep");
        System.exit(-1);
    }
    
    /**
     * Error al momento de leer mensaje del socket proviente del
     * drep correspondiente
     * @param c         ClientConnection de dcli
     */
    public void errorBufferGetLinea(ClientConnection c){
        System.err.println("ErrorHandler_Dcli: No ha sido posible recibir" +
                " correctamente el mensaje esperado del servidor drep");
        System.out.println("ErrorHandler_Dcli: Atención parece que el" +
                " servidor drep se encuentra caído, ¿Desea volver " +
                "a intentar establecer una conexión?(y/n)");
        InputStreamReader inp = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(inp);
        String resp;
        boolean again = true;
        try {
            while(again){
                resp = br.readLine();
                if (resp.equals("y")){
                    System.out.println("Intentando establecer nuevamente " +
                            "conexion con el servidor drep.......");
                    c.Connect();
                    this.control.iniciarSesion();
                    again = false;
                } else if (resp.equals("n")){
                    System.out.println("Finalizando dcli....");
                    c.Disconnect();
                    again = false;
                    System.exit(0);
                } else {
                    System.out.println("Opción no válida (y/n)");
                }
            }
        } catch (IOException ex) {
            System.exit(-1);
        }
    }

    /**
     * Error al momento de cerrar el BufferReader del socket del
     * drep correspondiente
     * @param e         Excepcion del sistema
     */
    public void errorCloseBufferGetLinea(IOException e){
        System.err.println("ErrorHandler_Dcli: Problemas cerrando el" +
                    "BufferedReader de GetLinea");

    }

    /**
     * Error al momento de abrir el BufferedReader para leer mensaje del
     * socket proviente del drep correspondiente
     * @param c         ClientConnection de dcli
     */
    public void errorGetLinea(ClientConnection c){
        System.err.println("ErrorHandler_Dcli: No ha sido posible abrir" +
                " correctamente el BufferedReader para recibir el mensaje " +
                "esperado del servidor drep, puede que este caído o haya" +
                "cerrado su socket de comunicación");
    }
    
    /**
     * Error al momento de abrir el PrintWriter para enviar el mensaje al
     * socket del drep correspondiente
     * @param c         ClientConnection del dcli
     * @param e         Error del sistema
     */
    public void errorSendLinea(ClientConnection c, IOException e){
        System.err.println("ErrorHandler_Dcli: No ha sido posible abrir" +
                " correctamente el PrintWriter para enviar el mensaje " +
                "esperado al servidor drep, puede que este caído o haya" +
                "cerrado su socket de comunicación");
    }

     /**
     * Error al momento de enviar el mensaje de solicitud nrep al drep
     */
    public void errorSolicitudNrep(){
        System.err.println("ErrorHandler_Dcli: No ha sido enviar solicitud" +
                "nrep correctamente al drep correspondiente, intentelo" +
                " de nuevo mas tarde");
    }

     /**
     * Error al momento de enviar el mensaje de solicitud newDcli al drep
     */
    public void errorSolicitudIniciarSesion(){
        System.err.println("ErrorHandler_Dcli: No ha sido posible enviar " +
                "solicitud IniciarSesion correctamente al drep " +
                "correspondiente, intentelo de nuevo mas tarde");
    }

    /**
     * Error al momento de enviar el mensaje de solicitud disconnectDcli
     * al drep
     */
    public void errorSolicitudCerrarSesion(){
        System.err.println("ErrorHandler_Dcli: No ha sido posible enviar " +
                "solicitud CerrarSesion correctamente al drep " +
                "correspondiente, intentelo de nuevo mas tarde");
    }

    /**
     * Error inesperado al momento de ejecutar el comando cat
     * @param e Excepcion lanzada por el sistema
     */
    public void errorCat(Exception e){
        System.err.println("ErrorHandler_Dcli: Se ha producido un error " +
                "inesperado intentar ejecutar el comando cat ");
    }

    /**
     * Error al momento de retorno del comando cat
     * @param e Excepcion lanzada por el sistema
     */
    public void errorRetornoCat(String archivo){
        System.err.println("ErrorHandler_Dcli: El archivo *" +archivo+
                "* solicitado en el comando cat no existe o no es alcanzable");
    }

    /**
     * Transferencia de archivo no satisfactoria al ejecutar el comando
     * sube
     */
    public void errorTransferenciaIncompletaSube(){
        System.err.println("ErrorHandler_Dcli: La transferencia no se " +
                "ha podido ejecutar de manera correcta (Comando Sube)");
    }

    /**
     * Transferencia de archivo no satisfactoria al ejecutar el comando
     * sube archivo no existe en ldir*
     * 
     * @param e         Excepcion lanzada por el sistema
     * @param archivo   Nombre del archivo no encontrado
     */
    public void errorArchivoNoExisteSube(FileNotFoundException e, String archivo){
        System.err.println("ErrorHandler_Dcli: El archivo *"+archivo+
                "* no existe en ldir (Comando Sube)");
    }

    /**
     * Transferencia de archivo no satisfactoria al ejecutar el comando
     * sube excepcion IO
     * @param e Excepcion lanzada por el sistema
     */
    public void errorTransferenciaSube(IOException e){
        System.err.println("ErrorHandler_Dcli: Se ha producido un " +
                "error no esperado en la transferencia (Comando Sube)");
    }

    /**
     * Transferencia de archivo no satisfactoria al ejecutar el comando
     * baja
     */
    public void errorTransferenciaIncompletaBaja(){
        System.err.println("ErrorHandler_Dcli: La transferencia no se " +
                "ha podido ejecutar de manera correcta (Comando Baja)");
    }

    /**
     * Transferencia de archivo no satisfactoria al ejecutar el comando
     * baja archivo no existe en rdir*
     * @param archivo   Nombre del archivo no encontrado
     */
    public void errorArchivoNoExisteBaja(String archivo){
        System.err.println("ErrorHandler_Dcli: El archivo *"+archivo+
                "* no existe en rdir (Comando Baja)");
    }

    /**
     * Transferencia de archivo no satisfactoria al ejecutar el comando
     * baja excepcion IO
     * @param e Excepcion lanzada por el sistema
     */
    public void errorTransferenciaBaja(IOException e){
        System.err.println("ErrorHandler_Dcli: Se ha producido un " +
                "error no esperado en la transferencia (Comando Baja)");
    }


     /**
     * Devuelve un mensaje de error cuando el puerto introducido en la línea de
     * comandos es inválido.
     *
     * @param puerto    el puerto inválido introducido
     */
    public void puertoInvalido(int puerto) {
        System.err.println("ErrorHandler_Dcli: Puerto "+puerto+" Inválido: " +
                "Debe ser mayor a 1023 y menor que 65536");
        System.exit(-1);
    }


    /**
     * Error intentando iniciar la sesion de un Dcli
     * @param   Conexion al drep
     */
    public void ErrorNewDcli(ClientConnection c){
        System.err.println("ErrorHandler_Dcli: No ha sido posible iniciar sesion parece " +
                "haber un problema de conexion con el servidor dmon " +
                "porfavor intente más tarde");
        c.Disconnect();
        System.exit(-1);
    }

    /**
     * Error intentando cerrar la sesion de un Dcli
     */
    public void ErrorDisconnectDcli(){
        System.err.println("ErrorHandler_Dcli: No ha sido posible cerrar sesion parece " +
                "haber un problema de conexion con el servidor " +
                "porfavor intente de nuevo");
        
    }

    /**
     * Error intentando solicitando nrep con dmon caido
     */
    public void ErrorNrep(){
        System.err.println("ErrorHandler_Dcli: No ha sido posible completar su solicitud *nrep* parece " +
                "haber un problema de conexion con el servidor " +
                "porfavor intente de nuevo");

    }

    /**
     * Error intentando solicitando rdir con dmon caido
     */
    public void ErrorRdir(){
        System.err.println("ErrorHandler_Dcli: No ha sido posible completar su solicitud *rdir* parece " +
                "haber un problema de conexion con el servidor " +
                "porfavor intente de nuevo");

    }

    /**
     * Error intentando solicitando tuser con dmon caido
     */
    public void ErrorTuser(){
        System.err.println("ErrorHandler_Dcli: No ha sido posible completar su solicitud *tuser* parece " +
                "haber un problema de conexion con el servidor " +
                "porfavor intente de nuevo");

    }

    //--------------------Protocolo-------------------


    /**
     * Recibimos un mensaje de error por parte del drep
     */
    public void protocolErrorNrep(){
        System.err.println("ProtocolHandler_Dcli: No ha sido posible" +
                " realizar su solicitud (Bad-Request)");
    }

    /**
     * Recibimos un mensaje de error por parte del drep
     */
    public void protocolErrorNewDcli(){
        System.err.println("ProtocolHandler_Dcli: No ha sido posible" +
                " realizar su solicitud (Bad-Request)");
    }

    /**
     * Recibimos un mensaje de error por parte del drep
     */
    public void protocolErrorDisconnectDcli(){
        System.err.println("ProtocolHandler_Dcli: No ha sido posible" +
                " realizar su solicitud (Bad-Request)");
    }
}
